﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using iNet.Tasks;

namespace iNet.Media.Imaging.Filters
{
	/// <summary>
	/// 灰階濾鏡。
	/// </summary>
	public class GrayscaleFilterTask : BitmapImageFilterTask
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 GrayscaleFilterTask 執行個體。
		/// </summary>
		public GrayscaleFilterTask()
		{ }
		/// <summary>
		/// 初始化新的 GrayscaleFilterTask 執行個體。
		/// </summary>
		/// <param name="sourceImage">來源點陣圖。</param>
		public GrayscaleFilterTask(IBitmapImage sourceImage)
			: base(sourceImage)
		{ }
		#endregion
		#region ApplyFilter
		/// <summary>
		/// 套用濾鏡至點陣圖。
		/// </summary>
		/// <param name="version">目前的工作版本。</param>
		/// <param name="filterData">套用濾鏡所需的資料。</param>
		/// <returns>True 表示濾鏡套用成功，False 表示失敗。</returns>
		protected override unsafe bool ApplyFilter(TaskVersion version, BitmapImageFilterData filterData)
		{
			//取得狀態
			int bytesPerPixel = filterData.BytesPerPixel;
			bool is16BitsColor = filterData.Is16BitsColor;

			//套用濾鏡
			int pixelWidth = filterData.PixelWidth;
			int pixelHeight = filterData.PixelHeight;
			int stride = filterData.Stride;
			byte* srcLineBuffer = (byte*)filterData.SourcePixelBuffer;
			byte* resultLineBuffer = (byte*)filterData.ResultPixelBuffer;
			for (int y = 0; y < pixelHeight; ++y, srcLineBuffer += stride, resultLineBuffer += stride)
			{
				//套用濾鏡
				byte* srcPixel = srcLineBuffer;
				byte* resultPixel = resultLineBuffer;
				for (int x = pixelWidth; x > 0; --x, srcPixel += bytesPerPixel, resultPixel += bytesPerPixel)
				{
					if (!is16BitsColor)
					{
						int b = *srcPixel;
						int g = *(srcPixel + 1);
						int r = *(srcPixel + 2);
						int i = ((r + g + b) / 3);
						*resultPixel = (byte)i;
						*(resultPixel + 1) = (byte)i;
						*(resultPixel + 2) = (byte)i;
					}
					else
					{
						int r = *(ushort*)srcPixel;
						int g = *(ushort*)(srcPixel + 2);
						int b = *(ushort*)(srcPixel + 4);
						int i = ((r + g + b) / 3);
						*(ushort*)resultPixel = (ushort)i;
						*(ushort*)(resultPixel + 2) = (ushort)i;
						*(ushort*)(resultPixel + 4) = (ushort)i;
					}
				}

				//中斷確認
				if ((y % 100) == 99)
				{
					if (this.IsCanceling)
						return true;
					this.ReportProgress(version, ((y + 1) * 100.0 / pixelHeight));
				}
			}
			return true;
		}
		#endregion
	}
}
